﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace SoftwareConsulting.BI11.Controls
{
    public partial class BlockingTextbox : UserControl
    {        
        private bool _blocked; //флаг блокировки
        private bool _hovered; //флаг подсветки
        private bool _selected; //флаг выделения
        private float _startFontSize; //начальный размер шрифта
        private Color _backColor; //цвет
        private Color _foreColor; //цвет рамки
        private Color _selectedBackColor; //цвет выделенного текстбокса
        private Color _selectedForeColor; //цвет рамки выделенного текстбокса
        private Color _hoveredBackColor; //цвет подсвеченного текстбокса
        private Color _hoveredForeColor; //цвет рамки подсвеченного текстбокса
        private Color _hoveredHoverColor; //цвет задней поверхности подсвеченного текстбокса        

        public event ValidatingText TextValidating;
        public event SelectedBox BoxSelected;        

        /// <summary>
        /// Сбрасывает все свойства компонента в установленные по умолчанию
        /// </summary>
        private void SetDefaults()
        {
            _blocked = false;
            _selected = false;
            _hovered = false;
            InternalTextBox.Font = new Font(InternalTextBox.Font.FontFamily, 8.25f);
            _startFontSize = InternalTextBox.Font.Size;
            _backColor = SystemColors.InactiveCaption;
            _foreColor = SystemColors.InactiveCaptionText;
            _selectedBackColor = SystemColors.MenuHighlight;
            _selectedForeColor = SystemColors.MenuText;
            _hoveredBackColor = SystemColors.ActiveCaption;
            _hoveredForeColor = SystemColors.ActiveCaptionText;
            _hoveredHoverColor = SystemColors.Highlight;
            UpdateColors();
            Text = string.Empty;
        }

        /// <summary>
        /// Обновляет цвета
        /// </summary>
        private void UpdateColors()
        {
            HoverPanel.BackColor = _hoveredHoverColor;
            HoverPanel.Visible = _hovered;
            if (_selected)
            {
                InternalTextBox.ForeColor = _selectedForeColor;
                InternalTextBox.BackColor = _selectedBackColor;
                return;
            }
            if (_hovered)
            {
                InternalTextBox.ForeColor = _hoveredForeColor;
                InternalTextBox.BackColor = _hoveredBackColor;                
                return;
            }
            InternalTextBox.ForeColor = _foreColor;
            InternalTextBox.BackColor = _backColor;
        }

        /// <summary>
        /// Возвращает/устанавливает флаг выделения
        /// </summary>
        public bool Selected
        {
            get
            {
                return _selected;
            }
            set
            {
                _selected = value;
                UpdateColors();
            }
        }

        /// <summary>
        /// Возвращает/устанавливает флаг подсветки
        /// </summary>
        public bool Hovered
        {
            get
            {
                return _hovered;
            }
            set
            {
                _hovered = value;
                UpdateColors();
            }
        }

        /// <summary>
        /// Устанавливает цвет текстбокса
        /// </summary>
        /// <param name="color"></param>
        public void SetBackColor(Color color)
        {
            _backColor = color;
            UpdateColors();
        }

        /// <summary>
        /// Устанавливает цвет шрифта текстбокса
        /// </summary>
        /// <param name="color"></param>
        public void SetForeColor(Color color)
        {
            _foreColor = color;
            UpdateColors();
        }

        /// <summary>
        /// Устанавливает цвет выделенного текстбокса
        /// </summary>
        /// <param name="color"></param>
        public void SetSelectedBackColor(Color color)
        {
            _selectedBackColor = color;
            UpdateColors();
        }

        /// <summary>
        /// Устанавливает цвет шрифта выделенного текстбокса
        /// </summary>
        /// <param name="color"></param>
        public void SetSelectedForeColor(Color color)
        {
            _selectedForeColor = color;
            UpdateColors();
        }

        /// <summary>
        /// Устанавливает цвет подсвеченного текстбокса
        /// </summary>
        /// <param name="color"></param>
        public void SetHoveredBackColor(Color color)
        {
            _hoveredBackColor = color;
            UpdateColors();
        }

        /// <summary>
        /// Устанавливает цвет шрифта подсвеченного текстбокса
        /// </summary>
        /// <param name="color"></param>
        public void SetHoveredForeColor(Color color)
        {
            _hoveredForeColor = color;
            UpdateColors();
        }

        /// <summary>
        /// Устанавливает цвет задней поверхности подсвеченного текстбокса
        /// </summary>
        /// <param name="color"></param>
        public void SetHoveredHoverColor(Color color)
        {
            _hoveredHoverColor = color;
            UpdateColors();
        }

        /// <summary>
        /// Возвращает формальный размер
        /// </summary>
        public Size FormalSize
        {
            get
            {
                TextBox hiddenBox = new TextBox();
                hiddenBox.Text = Text;
                Size result = hiddenBox.PreferredSize;
                hiddenBox.Dispose();                
                return result;
            }
        }        

        /// <summary>
        /// Возвращает/устанавливает текст текстбокса
        /// </summary>
        public override string Text
        {
            get
            {
                return InternalTextBox.Text;
            }
            set
            {                
                InternalTextBox.Text = value;
                UpdateInternalTextBoxSize();
            }
        }

        /// <summary>
        /// Возвращает/устанавливает шрифт текстбокса
        /// </summary>
        public override Font Font
        {
            get
            {
                return base.Font;
            }
            set
            {
                base.Font = value;
                InternalTextBox.Font = value;
            }
        }

        /// <summary>
        /// Возвращает/устанавливает флаг блокировки текстбокса
        /// </summary>
        public bool Blocked
        {
            get
            {
                return _blocked;
            }
            set
            {
                _blocked = value;
                InternalTextBox.Cursor = _blocked ? Cursors.Default : Cursors.IBeam;
                InternalTextBox.HideSelection = _blocked;
            }
        }

        public BlockingTextbox()
        {
            InitializeComponent();
            SetDefaults();
        }

        private void InternalTextBox_DoubleClick(object sender, EventArgs e)
        {
            Blocked = !Blocked;
        }

        /// <summary>
        /// Подгоняет размер текстбокса под оптимальный
        /// </summary>
        private void UpdateInternalTextBoxSize()
        {
            InternalTextBox.Size = InternalTextBox.PreferredSize;
            HoverPanel.Width = InternalTextBox.Width + 4;
            HoverPanel.Height = InternalTextBox.Height + 4;
        }

        private void InternalTextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (_blocked)
            {
                e.Handled = true;
                e.SuppressKeyPress = false;
            }
            else
            {
                UpdateInternalTextBoxSize();                
            }
        }

        private void InternalTextBox_Validating(object sender, CancelEventArgs e)
        {
            if (TextValidating != null)
            {
                string errorText = TextValidating(e);
                InternalErrorProvider.SetError(InternalTextBox, errorText);
                if (errorText == string.Empty)
                {
                    Blocked = true;
                }
            }
        }

        private void InternalTextBox_MouseClick(object sender, MouseEventArgs e)
        {
            Selected = true;
            if (BoxSelected != null)
            {
                BoxSelected(false);//TODO на самом деле true надо, если Ctrl был зажат
            }
        }

        private void InternalTextBox_Enter(object sender, EventArgs e)
        {
            Selected = true;
            if (BoxSelected != null)
            {
                BoxSelected(false);
            }
        }

        private void InternalTextBox_MouseEnter(object sender, EventArgs e)
        {
            Hovered = true;
        }

        private void InternalTextBox_MouseLeave(object sender, EventArgs e)
        {
            Hovered = false;
        }
    }

    public delegate string ValidatingText(CancelEventArgs e);    
    public delegate void SelectedBox(bool multiselectAdd);
}
